require 'digest/sha1'

class User < ActiveRecord::Base  

  #has_many(:friendships, :foreign_key => :user_a, :dependent => :destroy)
  #has_many(:reverse_friendships, :class_name => :Friendship,
  #    :foreign_key => "user_b_id", :dependent => :destroy)

  #has_many :users, :through => :friendships, :source => :user_b
  
  has_many :a_users, :class_name => 'Friendship', :foreign_key => :user_a_id  
  has_many :b_users, :class_name => 'Friendship', :foreign_key => :user_b_id
  
  has_many	:itinerary, :dependent => :destroy
  
  #has_many	:user_trip,	:foreign_key => "usr_id", :dependent=>:destroy
  #has_many 	:trip,		:foreign_key => "usr_id", :dependent=>:destroy
  
  has_many :trip, :foreign_key => "user_id", :dependent => :destroy
  has_many :user_trip, :dependent => :destroy
  has_many :on_trip, :through => :user_trip, :source => :trip
  
  has_many :comment, :dependent => :destroy
  has_many :itinerary, :through => :comment
  
  has_many :vote, :dependent => :destroy
  has_many :itinerary, :through => :vote

  
  include Authentication
  include Authentication::ByPassword
  include Authentication::ByCookieToken

  validates_presence_of     :login
  validates_length_of       :login,    :within => 2..40
  validates_uniqueness_of   :login
  validates_format_of       :login,    :with => Authentication.login_regex, :message => Authentication.bad_login_message

  validates_presence_of     :name
  validates_length_of       :name,     :maximum => 100
  
  validates_presence_of     :lastname
  validates_length_of       :lastname,     :maximum => 100

  validates_presence_of     :email
  validates_length_of       :email,    :within => 6..100 #r@a.wk
  validates_uniqueness_of   :email
  validates_format_of       :email,    :with => Authentication.email_regex, :message => Authentication.bad_email_message
 

  # HACK HACK HACK -- how to do attr_accessible from here?
  # prevents a user from submitting a crafted form that bypasses activation
  # anything else you want your user to change should be added here.
  attr_accessible :login, :email, :name, :name2, :lastname, :lastname2, :password, :password_confirmation, :reset_code


  # Activates the user in the database.
  def activate!
    @activated = true
    self.activated_at = Time.now.utc
    self.activation_code = nil
    save(false)
  end

  # Returns true if the user has just been activated.
  def recently_activated?
    @activated
  end

  def active?
    # the existence of an activation code means they have not activated yet
    activation_code.nil?
  end
  
  def recently_activated?
    @activated
  end
  
  def create_reset_code
    @reset = true
    self.attributes = {:reset_code => Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )}
    save(false)
  end 
  
  def recently_reset?
    @reset
  end 

  def delete_reset_code
    self.attributes = {:reset_code => nil}
    save(false)
  end
  

  # Authenticates a user by their login name and unencrypted password.  Returns the user or nil.
  #
  # uff.  this is really an authorization, not authentication routine.  
  # We really need a Dispatch Chain here or something.
  # This will also let us return a human error message.
  #
  def self.authenticate(login, password)
    return nil if login.blank? || password.blank?
    u = find_by_login(login.downcase) # need to get the salt
    u && u.authenticated?(password) ? u : nil
  end

  def login=(value)
    write_attribute :login, (value ? value.downcase : nil)
  end

  def email=(value)
    write_attribute :email, (value ? value.downcase : nil)
  end

  protected
    def make_activation_code
		self.activation_code = self.class.make_token
    end
  
end
